package com.github.dote.mio.daemon;

import com.github.dote.mio.client.IOClient;
import com.github.dote.mio.protocal.Packet;
import com.github.dote.mio.protocal.PacketType;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class KeepAliveDaemon {

    public interface KeepAliveCallback {
        public void onLostKeepAlive();

    }

    public static int NETWORK_CONNECTION_TIME_OUT = 10 * 1000;
    public static int KEEP_ALIVE_INTERVAL = 3000;//1000;

    private boolean keepAliveRunning = false;
    private long lastGetKeepAliveResponseFromServerTimstamp = 0;
    private boolean _excuting = false;
    private Timer timer = null;
    private IOClient client;
    private KeepAliveCallback callback;

    public KeepAliveDaemon(IOClient client) {
        this.client = client;
        init();
    }

    private void init() {
        timer = new Timer(KEEP_ALIVE_INTERVAL, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                run();
            }
        });
    }

    private Packet createKeepAlivePacket() {
        Packet packet = new Packet();
        packet.setType(PacketType.KEEP_ALIVE);
        packet.setSessionId("0");
        packet.setDataContent("");
        packet.setAck(false);
        return packet;
    }

    public void run() {
        if (!_excuting) {
            boolean willStop = false;
            _excuting = true;

            boolean sendSuccess = client.send(createKeepAlivePacket());


            boolean isInitialedForKeepAlive = (lastGetKeepAliveResponseFromServerTimstamp == 0);
            if (sendSuccess && lastGetKeepAliveResponseFromServerTimstamp == 0)
                lastGetKeepAliveResponseFromServerTimstamp = System.currentTimeMillis();

            if (!isInitialedForKeepAlive) {
                long now = System.currentTimeMillis();
                if ((now - lastGetKeepAliveResponseFromServerTimstamp >= NETWORK_CONNECTION_TIME_OUT) || (now - lastGetKeepAliveResponseFromServerTimstamp >= NETWORK_CONNECTION_TIME_OUT/2.5 && client!=null && !client.isConnected())) {
                    stop();
                    willStop = true;
                }
            }


            _excuting = false;
            if (willStop) {
                timer.stop();
                if (callback != null) {
                    callback.onLostKeepAlive();
                }

            }
        }
    }

    public void stop() {
        if (timer != null)
            timer.stop();
        keepAliveRunning = false;
        _excuting = false;
        lastGetKeepAliveResponseFromServerTimstamp = 0;
    }

    public void start(boolean immediately) {
        stop();
        if (immediately)
            timer.setInitialDelay(0);
        else
            timer.setInitialDelay(KEEP_ALIVE_INTERVAL);
        timer.start();

        keepAliveRunning = true;
    }

    public void send(){
        if(client!=null){
            client.send(createKeepAlivePacket());
        }
    }

    public boolean isKeepAliveRunning() {
        return keepAliveRunning;
    }

    public void updateGetKeepAliveResponseFromServerTimstamp() {
        lastGetKeepAliveResponseFromServerTimstamp = System.currentTimeMillis();
    }

    public IOClient getClient() {
        return client;
    }

    public void setClient(IOClient client) {
        this.client = client;
    }

    public KeepAliveDaemon(KeepAliveCallback callback) {
        this.callback = callback;
    }



    public KeepAliveCallback getCallback() {
        return callback;
    }

    public void setCallback(KeepAliveCallback callback) {
        this.callback = callback;
    }
}
